package cn.wolfcode.web.controller;

import cn.wolfcode.common.domain.UserInfo;
import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.common.web.anno.RequireLogin;
import cn.wolfcode.domain.OrderInfo;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.mq.MQConstant;
import cn.wolfcode.mq.OrderMessage;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.IOrderInfoService;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.util.UserUtil;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.ConcurrentHashMap;


@RestController
@RequestMapping("/order")
@Slf4j
public class OrderInfoController {
    @Autowired
    private ISeckillProductService seckillProductService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private IOrderInfoService orderInfoService;

    public static ConcurrentHashMap<Long, Boolean> map = new ConcurrentHashMap<>();//本地标识

    @RequestMapping("doSeckill")
    @RequireLogin//判断是否登录
    public Result<String> doSeckill(int time, Long seckillId, HttpServletRequest request) {
        /*
        1、判断用户是否登录 @RequireLogin
        2、判断参数是否有效
        3、判断商品是否在活动时间内
        4、判断库存是否足够
        5、判断用户时候重复下单
        6、执行描述业务逻辑
         */

        //判断参数是否有效
        if (StringUtils.isEmpty(time + "") || StringUtils.isEmpty(seckillId + "")) {
            throw new BusinessException(SeckillCodeMsg.OPT_ERROR);
        }

        SeckillProductVo seckillProductVo = seckillProductService.find(time, seckillId);

        //减少优化访问redis（减少网络标识）
        Boolean aBoolean = map.get(seckillId);
        if (aBoolean != null && aBoolean) {
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }

        //判断商品时候在活动的时间内
//        boolean legalTime = DateUtil.isLegalTime(seckillProductVo.getStartDate(), time);
//        if (!legalTime) {
//            throw new BusinessException(SeckillCodeMsg.OPT_ERROR);
//        }

        //判断库存时候足够
//        if (seckillProductVo.getStockCount() <= 0) {
//            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
//        }


        //利用redis控制进入service的人数
        Long increment = redisTemplate.opsForHash().increment(SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(time + ""),
                seckillId + "", -1);
        if (increment < 0) {
            map.put(seckillId, true);
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }

        //判断用户时候重复下单
        /**
         *当下单成功的时候，向redis中进行添加一条数据，以Set的形式进行存储
         */
        String token = request.getHeader("token");
        UserInfo user = UserUtil.getUser(redisTemplate, token);//从redis中获取用户的基本的信息
        Boolean member = redisTemplate.opsForSet().isMember(SeckillRedisKey.SECKILL_ORDER_SET.getRealKey(time + "")
                , seckillId + ":" + user.getPhone());
        if (member) {
            throw new BusinessException(SeckillCodeMsg.REPEAT_SECKILL);
        }

        //秒杀业务逻辑(同步下单的方式)
//      String orderNo = orderInfoService.doSeckill(time, seckillId, user.getPhone());

        //秒杀业务逻辑(异步下单的方式)
        OrderMessage orderMessage = new OrderMessage();
        orderMessage.setTime(time);
        orderMessage.setSeckillId(seckillId);
        orderMessage.setToken(token);
        orderMessage.setUserPhone(user.getPhone());
        rocketMQTemplate.sendOneWay(MQConstant.ORDER_PEDDING_TOPIC, orderMessage);
        return Result.success("正在抢购，请稍后...");
    }

    @RequestMapping("find")
    public Result<OrderInfo> find(String orderNo, HttpServletRequest request) {
        //参数的校验
        if (StringUtils.isEmpty(orderNo)) {
            throw new BusinessException(SeckillCodeMsg.OPT_ERROR);
        }
        //根据订单编号到数据库中查找数据
        OrderInfo orderInfo = orderInfoService.find(orderNo);
        if (orderInfo == null) {
            throw new BusinessException(SeckillCodeMsg.OPT_ERROR);
        }
        //当前的用户只能查看自己的订单消息
        String token = request.getHeader("token");
        UserInfo user = UserUtil.getUser(redisTemplate, token);
        if (!orderInfo.getUserId().equals(user.getPhone())) {
            throw new BusinessException(SeckillCodeMsg.OPT_ERROR);
        }
        return Result.success(orderInfo);
    }
}
